/**
 * auther:zhi/wx:Ms-zhi999
 * date:2018/04/16
 */
const _host = Symbol('host');
const _header = Symbol('header');
const _feature = Symbol('feature');
const _uploadUrl = Symbol('uploadUrl');
module.exports = class Api {
  constructor(host = ''){this[_host] = host.toString();this[_feature] = [];}
  get host() { return this[_host];}
  set host(str) { if (str) this[_host] = str.toString(); }
  set header(obj) { this[_header] = Object.assign({}, obj) }
  get header() { return this[_header] }
  set uploadUrl(str) { if (str) this[_uploadUrl] = `${this.host}${str.toString()}` }
  get uploadUrl() { return this[_uploadUrl] }getFeature(str) {
    if (str) {
      let obj = this[_feature].find(cur => cur.name == str)
      return obj;
    } else {
      let arr = this[_feature].map(cur => cur)
      return arr;
    }
  }
  orginMethod(method,url,data,header){return new Promise((resolve,reject) =>{
    // data.token = wx.getStorageSync('token');
    wx.request({url:url,method:method,header:header,data:data,success:(res) =>{
    // console.log(res.data)
    if(res.data.status == 0){
      wx.removeStorageSync('token')
      wx.navigateTo({
        url: '/pages/login/login',
      })
    }
    if(res.statusCode == 200){resolve(res)}else{if(res.data.msg == 'Token is not valid'){
      wx.removeStorageSync('token')
    }
    reject(res)}},fail:(res) =>{reject(res)}})})}
  method(obj) {
    let { method = 'GET', url = null, data = {}, header = {} } = obj;
    if (!url) { return Promise.reject(`Unknown url "${this.host}${url}"`) };
    method = method.toLocaleUpperCase();
    url = `${this.host}${url}`;
    header = Object.assign({}, this.header, header);
    if(data.params){url = `${url}/${data.params}`;delete data.params}
    return this.orginMethod(method, url, data, header);
  }
  addMethod(obj) {
    let answer, has, {
      name,
      url,
      method = 'GET',
      data = {},
      header = {}
    } = obj;
    if (!name) throw new Error('Unknown name in Api.addMethod');
    has = this[_feature].some(cur => cur.name == name);
    if (has) throw new Error(`Already set Api.${name} method in Api.addMethod`);
    this[_feature].push({name,url,method,data,header});
    answer = this.setMethod(obj);
    return answer;
  }
  addMethods(arrObj) {
    if (arrObj instanceof Array) {
      let result;
      result = arrObj.reduce((acc, cur) => {
        try {
          this.addMethod(cur)
          return acc + 1
        } catch (err) {
          return acc
        }
      }, 0);
      return [arrObj.length, result];
    }
  }
  upDateMethod(obj) {
    let answer, has, newObj, {
      name,
      url,
      method,
      data,
      header
    } = obj;
    if (!name) throw new Error('Unknown name in Api.upDateMethod');
    has = this[_feature].some(cur => cur.name == name);
    if (!has) throw new Error(`Api.${name} method did not set in Api.upDateMethod`);
    this[_feature] = this[_feature].map(cur => {
      if(cur.name == name){for(let title in obj){if(cur[title]) cur[title] = obj[title]}}
      return cur
    });
    newObj = this[_feature].find(cur => cur.name == name)
    answer = this.setMethod(newObj);
    return answer;
  }
 upDateMethods(arrObj) {
    if (arrObj instanceof Array) {
      let result;
      result = arrObj.reduce((acc, cur) => {
        try {
          this.upDateMethod(cur)
          return acc + 1
        } catch (err) {
          console.log(err)
          return acc
        }
      }, 0);
      return [arrObj.length, result];
    } else {
      throw new Error('Unknown params, please check Api.upDateMethods')
    }
  }
  setMethod(obj) {
    let {
      name,
      url,
      method,
      data,
      header
    } = obj;
    this[name] = (obj = {}) => {
      let d, h;
      if (obj.header) {
        h = Object.assign({}, header, obj.header);
        delete obj.header;
      } else h = header;
      d = Object.assign({}, data, obj);
      return this.method({
        url,
        method,
        data: d,
        header: h
      })
    };
    return true;
  }
  get(url,data,header){return this.method({method:'GET',url,data,header})}
  post(url,data,header){return this.method({method:'POST',url,data,header})}
  put(url,data,header){return this.method({method:'PUT',url,data,header})}
  del(url,data,header){return this.method({method:'DELETE',url,data,header})}
  upload(obj, header) {
    let arr = [],
      data = {};
    data.url = this.uploadUrl;
    data.header = Object.assign({}, this.header, header);
    if (obj.formData) {
      data.formData = obj.formData
      delete obj.formData
    }
    for (let value of Object.entries(obj)) {
      if (Array.isArray(value[1])) {
        for (let va of value[1]) {
          arr.push(new Promise((resolve, reject) => {
            data.success = res => resolve(res);
            data.fail = res => reject(res)
            wx.uploadFile({ ...data,
              name: value[0],
              filePath: va
            })
          }))
        }
      } else if (value[1]) {
        arr.push(new Promise((resolve, reject) => {
          data.success = res => resolve(res);
          data.fail = res => reject(res)
          wx.uploadFile({ ...data,
            name: value[0],
            filePath: value[1]
          })
        }))
      }
    }
    return Promise.all(arr)
  }

}